import 'package:flutter/material.dart';
import 'package:private_journey/States.dart';
import 'package:private_journey/services/DbService.dart';
import 'package:signals/signals_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart' as shadcn;

import '../GlobalInfo.dart';

class Home extends StatefulWidget {
  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  late VoidCallback _unsubscribe; // 用于存储取消订阅的函数
  List<shadcn.SelectItemButton> keys = [];
  var currentSelectKey = Signal<String>('');

  @override
  void dispose() {
    _unsubscribe(); // 取消订阅
    keys.clear();
    currentSelectKey.dispose();
    isInKeyboardPage = false;
    super.dispose();
  }

  shadcn.SelectItemButton buildKeySelectItem(String text) {
    return shadcn.SelectItemButton(value: text, child: Text(text));
  }

  void initKeys() {
    keys.add(buildKeySelectItem('Esc'));
    keys.add(buildKeySelectItem('F1'));
    keys.add(buildKeySelectItem('F2'));
    keys.add(buildKeySelectItem('F3'));
    keys.add(buildKeySelectItem('F4'));
    keys.add(buildKeySelectItem('F5'));
    keys.add(buildKeySelectItem('F6'));
    keys.add(buildKeySelectItem('F7'));
    keys.add(buildKeySelectItem('F8'));
    keys.add(buildKeySelectItem('F9'));
    keys.add(buildKeySelectItem('F10'));
    keys.add(buildKeySelectItem('F11'));
    keys.add(buildKeySelectItem('F12'));

    keys.add(buildKeySelectItem('`'));
    keys.add(buildKeySelectItem('1'));
    keys.add(buildKeySelectItem('2'));
    keys.add(buildKeySelectItem('3'));
    keys.add(buildKeySelectItem('4'));
    keys.add(buildKeySelectItem('5'));
    keys.add(buildKeySelectItem('6'));
    keys.add(buildKeySelectItem('7'));
    keys.add(buildKeySelectItem('8'));
    keys.add(buildKeySelectItem('9'));
    keys.add(buildKeySelectItem('0'));
    keys.add(buildKeySelectItem('-'));
    keys.add(buildKeySelectItem('='));
    keys.add(buildKeySelectItem('Backspace'));

    keys.add(buildKeySelectItem('Tab'));
    keys.add(buildKeySelectItem('Q'));
    keys.add(buildKeySelectItem('W'));
    keys.add(buildKeySelectItem('E'));
    keys.add(buildKeySelectItem('R'));
    keys.add(buildKeySelectItem('T'));
    keys.add(buildKeySelectItem('Y'));
    keys.add(buildKeySelectItem('U'));
    keys.add(buildKeySelectItem('I'));
    keys.add(buildKeySelectItem('O'));
    keys.add(buildKeySelectItem('P'));
    keys.add(buildKeySelectItem('['));
    keys.add(buildKeySelectItem(']'));
    keys.add(buildKeySelectItem('\\'));

    keys.add(buildKeySelectItem('CapsLock'));
    keys.add(buildKeySelectItem('A'));
    keys.add(buildKeySelectItem('S'));
    keys.add(buildKeySelectItem('D'));
    keys.add(buildKeySelectItem('F'));
    keys.add(buildKeySelectItem('G'));
    keys.add(buildKeySelectItem('H'));
    keys.add(buildKeySelectItem('J'));
    keys.add(buildKeySelectItem('K'));
    keys.add(buildKeySelectItem('L'));
    keys.add(buildKeySelectItem(';'));
    keys.add(buildKeySelectItem('\''));
    keys.add(buildKeySelectItem('Enter'));

    keys.add(buildKeySelectItem('LShift'));
    keys.add(buildKeySelectItem('Z'));
    keys.add(buildKeySelectItem('X'));
    keys.add(buildKeySelectItem('C'));
    keys.add(buildKeySelectItem('V'));
    keys.add(buildKeySelectItem('B'));
    keys.add(buildKeySelectItem('N'));
    keys.add(buildKeySelectItem('M'));
    keys.add(buildKeySelectItem(','));
    keys.add(buildKeySelectItem('.'));
    keys.add(buildKeySelectItem('/'));
    keys.add(buildKeySelectItem('RShift'));

    keys.add(buildKeySelectItem('LCtrl'));
    keys.add(buildKeySelectItem('Win'));
    keys.add(buildKeySelectItem('LAlt'));
    keys.add(buildKeySelectItem('Space'));
    keys.add(buildKeySelectItem('RAlt'));
    keys.add(buildKeySelectItem('Win'));
    keys.add(buildKeySelectItem('RCtrl'));
  }

  @override
  void initState() {
    super.initState();
    initKeys();
    _unsubscribe = keyCodeInfo.subscribe((s) async {
      if (s.code == -1) {
        return;
      }
      if (keyMap.value.keys.where((e) {
            return e.code == s.code;
          }).firstOrNull !=
          null) {
        return;
      }
      await listenKeyPress(s);
    });
    isInKeyboardPage = true;
  }

  Future<void> listenKeyPress(KeyCodeInfo s) async {
    if (isInKeyboardPage) {
      if (!keyMap.value.keys.contains(s)) {
        await showDialog(
          context: context,
          builder: (context) {
            return Watch((context) {
              return AlertDialog(
                title: Text('请选择刚刚的按键'),
                content: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    shadcn.Select<String>(
                      itemBuilder: (context, item) {
                        return Text(item);
                      },
                      popupConstraints: const BoxConstraints(
                        maxHeight: 300,
                        maxWidth: 200,
                      ),
                      onChanged: (value) {
                        currentSelectKey.value = value!;
                      },
                      value: currentSelectKey.value,
                      placeholder: const Text('按键'),
                      popup: shadcn.SelectPopup(
                        items: shadcn.SelectItemList(children: keys),
                      ),
                    ),
                    Row(
                      children: [
                        shadcn.TextButton(
                          child: shadcn.Text('确认'),
                          onPressed: () {
                            s.key = currentSelectKey.value;
                            Navigator.of(context).pop();
                          },
                        ),
                        shadcn.TextButton(
                          child: shadcn.Text('取消'),
                          onPressed: () {
                            currentSelectKey.value = '';
                            Navigator.of(context).pop();
                          },
                        ),
                      ],
                    ),
                  ],
                ),
              );
            });
          },
        );
        updateUserKeysConfig(s);
        Map<KeyCodeInfo, int> map = Map.from(keyMap.value);
        if (map[s] == null && s.key != '') {
          map[s] = 1;
          keyMap.value = map;
        } else {
          currentSelectKey.value = '';
          keyCodeInfo.value = KeyCodeInfo('', -1);
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Watch((c) {
      return MouseRegion(
        onHover: (e) {
          position.value = e.localPosition;
        },
        child: CustomPaint(
          painter: KeyboardPage(c, keyCodeInfos.value, position.value),
        ),
      );
    });
  }
}

var position = Signal<Offset>(Offset.zero);

class KeyInfo {
  String key;
  double scale;
  String mapKey;
  double extraWidth;

  KeyInfo(this.key, this.scale, {this.extraWidth = 0.0, this.mapKey = ''});
}

final double leftRightMargin = 20.0;
final double spacing = 10.0; // Space between keys horizontally and vertically

class KeyboardPage extends CustomPainter {
  final BuildContext context;
  final List<KeyCodeInfo> keyCodeInfo;
  Offset offset;

  KeyboardPage(this.context, this.keyCodeInfo, this.offset);

  final List<KeyInfo> firstLineKeys = [
    KeyInfo('Esc', 1.0, mapKey: 'Esc'),
    KeyInfo('F1', 1.0, mapKey: 'F1'),
    KeyInfo('F2', 1.0, mapKey: 'F2'),
    KeyInfo('F3', 1.0, mapKey: 'F3'),
    KeyInfo('F4', 1.0, mapKey: 'F4'),
    KeyInfo('F5', 1.0, mapKey: 'F5'),
    KeyInfo('F6', 1.0, mapKey: 'F6'),
    KeyInfo('F7', 1.0, mapKey: 'F7'),
    KeyInfo('F8', 1.0, mapKey: 'F8'),
    KeyInfo('F9', 1.0, mapKey: 'F9'),
    KeyInfo('F10', 1.0, mapKey: 'F10'),
    KeyInfo('F11', 1.0, mapKey: 'F11'),
    KeyInfo('F12', 1.0, mapKey: 'F12'),
    KeyInfo('Delete', 1.0, mapKey: 'Delete'),
    KeyInfo('PrtSc', 1.0, mapKey: 'PrtSc'),
  ];
  final List<KeyInfo> secondLineKeys = [
    KeyInfo('`', 1.0, mapKey: '`'),
    KeyInfo('1', 1.0, mapKey: '1'),
    KeyInfo('2', 1.0, mapKey: '2'),
    KeyInfo('3', 1.0, mapKey: '3'),
    KeyInfo('4', 1.0, mapKey: '4'),
    KeyInfo('5', 1.0, mapKey: '5'),
    KeyInfo('6', 1.0, mapKey: '6'),
    KeyInfo('7', 1.0, mapKey: '7'),
    KeyInfo('8', 1.0, mapKey: '8'),
    KeyInfo('9', 1.0, mapKey: '9'),
    KeyInfo('0', 1.0, mapKey: '0'),
    KeyInfo('-', 1.0, mapKey: '-'),
    KeyInfo('=', 1.0, mapKey: '='),
    KeyInfo('Backspace', 2.0, extraWidth: 10.0, mapKey: 'Backspace'),
  ];

  // Add more lines as needed...
  final List<KeyInfo> thirdLineKeys = [
    KeyInfo('Tab', 1.5, mapKey: 'Tab'),
    KeyInfo('Q', 1.0, mapKey: 'Q'),
    KeyInfo('W', 1.0, mapKey: 'W'),
    KeyInfo('E', 1.0, mapKey: 'E'),
    KeyInfo('R', 1.0, mapKey: 'R'),
    KeyInfo('T', 1.0, mapKey: 'T'),
    KeyInfo('Y', 1.0, mapKey: 'Y'),
    KeyInfo('U', 1.0, mapKey: 'U'),
    KeyInfo('I', 1.0, mapKey: 'I'),
    KeyInfo('O', 1.0, mapKey: 'O'),
    KeyInfo('P', 1.0, mapKey: 'P'),
    KeyInfo('[', 1.0, mapKey: '['),
    KeyInfo(']', 1.0, mapKey: ']'),
    KeyInfo('\\', 1.5, extraWidth: 10.0, mapKey: '\\'),
  ];
  final List<KeyInfo> fourthLineKeys = [
    KeyInfo('Caps Lock', 2.0, extraWidth: 10.0, mapKey: 'CapsLock'),
    KeyInfo('A', 1.0, mapKey: 'A'),
    KeyInfo('S', 1.0, mapKey: 'S'),
    KeyInfo('D', 1.0, mapKey: 'D'),
    KeyInfo('F', 1.0, mapKey: 'F'),
    KeyInfo('G', 1.0, mapKey: 'G'),
    KeyInfo('H', 1.0, mapKey: 'H'),
    KeyInfo('J', 1.0, mapKey: 'J'),
    KeyInfo('K', 1.0, mapKey: 'K'),
    KeyInfo('L', 1.0, mapKey: 'L'),
    KeyInfo(';', 1.0, mapKey: ';'),
    KeyInfo("'", 1.0, mapKey: "'"),
    KeyInfo('Enter', 2.0, extraWidth: 10.0, mapKey: 'Enter'),
  ];
  final List<KeyInfo> fifthLineKeys = [
    KeyInfo('Shift', 2.5, extraWidth: 15.0, mapKey: 'LShift'),
    KeyInfo('Z', 1.0, mapKey: 'Z'),
    KeyInfo('X', 1.0, mapKey: 'X'),
    KeyInfo('C', 1.0, mapKey: 'C'),
    KeyInfo('V', 1.0, mapKey: 'V'),
    KeyInfo('B', 1.0, mapKey: 'B'),
    KeyInfo('N', 1.0, mapKey: 'N'),
    KeyInfo('M', 1.0, mapKey: 'M'),
    KeyInfo(',', 1.0, mapKey: ','),
    KeyInfo('.', 1.0, mapKey: '.'),
    KeyInfo('/', 1.0, mapKey: '/'),
    KeyInfo('Shift', 2.5, extraWidth: 15.0, mapKey: 'RShift'),
  ];
  final List<KeyInfo> sixthLineKeys = [
    KeyInfo('Ctrl', 1.0, mapKey: 'LCtrl'),
    KeyInfo('Win', 1.0, mapKey: 'Win'),
    KeyInfo('Alt', 1.0, mapKey: 'LAlt'),
    KeyInfo('Space', 9, extraWidth: 80.0, mapKey: 'Space'),
    KeyInfo('Alt', 1.0, mapKey: 'RAlt'),
    KeyInfo('Fn', 1.0),
    KeyInfo('Ctrl', 1.0, mapKey: 'RCtrl'),
  ];

  // --- Layout Constants ---

  final double topBottomMargin = 50.0;

  double calStandardWidth(Size size) {
    // --- Calculate Standard Key Width ---
    // Base the width calculation on the first row (or potentially the widest row)
    // 1. Calculate total horizontal space available for keys and spacing
    final double availableWidth = size.width - leftRightMargin * 2;

    // 2. Calculate the total number of standard key width 'units' in the first row
    final double totalUnitsFirstRow = firstLineKeys.fold(
      0.0,
      (sum, key) => sum + key.scale,
    );

    // 3. Calculate the total spacing width needed for the first row
    final double totalSpacingWidthFirstRow =
        (firstLineKeys.length > 1) ? (firstLineKeys.length - 1) * spacing : 0;

    // 4. Calculate the width of a single standard key unit (scale = 1.0)
    // Ensure totalUnitsFirstRow is not zero to avoid division by zero
    final double standardKeyWidth =
        totalUnitsFirstRow > 0
            ? (availableWidth - totalSpacingWidthFirstRow) / totalUnitsFirstRow
            : 0; // Handle case with no keys

    if (standardKeyWidth <= 0) {
      logger.e(
        'Warning: Calculated standard key width is zero or negative. Check margins, spacing, and key data.',
      );
      return -100; // Avoid drawing if width is invalid
    }
    return standardKeyWidth;
  }

  @override
  void paint(Canvas canvas, Size size) {
    final paint =
        Paint()
          ..color =
              Colors
                  .red // Use cascade operator for cleaner setup
          ..style = PaintingStyle.stroke
          ..strokeWidth = 1.0; // Optional: define stroke width

    // Draw First Line
    _drawRow(canvas, paint, [
      firstLineKeys,
      secondLineKeys,
      thirdLineKeys,
      fourthLineKeys,
      fifthLineKeys,
      sixthLineKeys,
    ], size);
  }

  void _drawRow(
    Canvas canvas,
    Paint paint,
    List<List<KeyInfo>> keysList,
    Size size,
  ) {
    final double keyHeight = 50.0; // Standard height for keys
    double standardKeyWidth = calStandardWidth(size);

    for (var i = 0; i < keysList.length; i++) {
      double currentOffsetX = leftRightMargin;
      double startY = topBottomMargin + i * (keyHeight + spacing);
      var keys = keysList[i];
      for (var j = 0; j < keys.length; j++) {
        final key = keys[j];
        final double actualKeyWidth =
            standardKeyWidth * key.scale +
            key.extraWidth; // Width for this specific key

        // Create the rectangle for the key
        final Rect keyRect = Rect.fromLTWH(
          currentOffsetX,
          startY,
          actualKeyWidth,
          keyHeight,
        );

        // 保存当前paint状态
        final originalStyle = paint.style;
        final originalColor = paint.color;

        bool isHover = keyRect.contains(offset);
        var mapx = {};
        var code = -1;
        keyMap.value.forEach((k, v) {
          mapx[k.key] = v;
          if (k.key == key.mapKey) {
            code = k.code;
          }
        });
        var kkk =
            keyCodeInfo.where((e) {
              return e.code == code;
            }).firstOrNull;
        var t = (code == kkk?.code && kkk?.state == KeyState.pressed);

        if (isHover || t) {
          paint
            ..style = PaintingStyle.fill
            ..color = Colors.blue;
        }
        // Draw the key border
        canvas.drawRect(keyRect, paint);
        // 右上角画一个圆
        canvas.drawCircle(Offset(keyRect.right, keyRect.top), 10, paint);
        final textColor = Theme.of(context).colorScheme.primaryContainer;

        if (mapx[key.mapKey] != null) {
          final countPainter = TextPainter(
            text: TextSpan(
              text: mapx[key.mapKey].toString(),
              style: TextStyle(
                color: Colors.black,
                fontSize: 14,
              ), // Style the text
            ),
            textDirection: TextDirection.ltr,
            textAlign: TextAlign.center,
          );
          countPainter.layout(
            minWidth: 0,
            maxWidth: actualKeyWidth, // Constrain text layout width if needed
          );
          countPainter.paint(canvas, Offset(keyRect.right, keyRect.top));
        }

        // 恢复paint状态
        paint
          ..style = originalStyle
          ..color = originalColor;

        // --- Draw Text ---
        final textPainter = TextPainter(
          text: TextSpan(
            text: key.key,
            style: TextStyle(color: textColor, fontSize: 14), // Style the text
          ),
          textDirection: TextDirection.ltr,
          textAlign: TextAlign.center,
        );
        textPainter.layout(
          minWidth: 0,
          maxWidth: actualKeyWidth, // Constrain text layout width if needed
        );

        // Calculate position to center the text within the key rectangle
        final double textX =
            keyRect.left + (keyRect.width - textPainter.width) / 2;
        final double textY =
            keyRect.top + (keyRect.height - textPainter.height) / 2;

        // Paint the text
        textPainter.paint(canvas, Offset(textX, textY));

        // Update the horizontal offset for the next key
        currentOffsetX += actualKeyWidth + spacing;
      }
    }
  }

  @override
  bool shouldRepaint(covariant KeyboardPage oldDelegate) {
    return oldDelegate.keyCodeInfo != keyCodeInfo ||
        oldDelegate.offset != offset;
  }
}

class TransferData {
  Rect rect;
  double actualKeyWidth;
  String text;

  TransferData(this.rect, this.actualKeyWidth, this.text);

  Offset circle() {
    return Offset(rect.right, rect.top);
  }
}
